import ubluetooth as bt
from ble.const import BLEConst
from ble.tools import BLETools
from ble.profile.manager import ProfileManager
from ble.services import *
from ble.characteristics import *
from ble.descriptors import *


class BLELibTest(object):
	def __init__(self):
		self.__ble = bt.BLE()
		self.__profile = ProfileManager()
		self.__conn_handle = None

		self.__profile.add_services(
			BatteryService().add_characteristics(
				Characteristics(BLEConst.Characteristics.BATTERY_LEVEL, BLEConst.CharacteristicFlags.BATTERY_LEVEL_)
			),
			HumanInterfaceDevice().add_characteristics(
				Characteristics(BLEConst.Characteristics.REPORT, BLEConst.CharacteristicFlags.REPORT_).add_descriptors(
					ClientCharacteristicConfiguration(),
				)
			),
		)

		self.__ble.active(False)
		print("activating ble...")
		self.__ble.active(True)
		print("ble activated")

		self.__services = self.__profile.get_services()
		self.__ble.irq(self.__irq)
		self.__register_services()

		self.__adv_payload = BLETools.advertising_generic_payload(
			services=self.__profile.get_services_uuid(),
			appearance=BLEConst.Appearance.GENERIC_HEART_RATE_SENSOR
		)
		self.__resp_payload = BLETools.advertising_resp_payload(
			name="BLELibTest"
		)

		self.__advertise()

	def __register_services(self):
		(
			(
				self.__handle_battery_level,
			),
			(
				self.__handle_report,
				self.__handle_report_desc,
			),
		) = self.__ble.gatts_register_services(self.__services)

		print("services registed")

		self.update_battery_level()

	def __advertise(self, interval_us=100000):
		self.__ble.gap_advertise(None)
		self.__ble.gap_advertise(interval_us, adv_data=self.__adv_payload, resp_data=self.__resp_payload)
		print("advertising...")

	def __irq(self, event, data):
		if event == BLEConst.IRQ.IRQ_CENTRAL_CONNECT:
			self.__conn_handle, _, addr, = data
			print("[{}] connected, handle: {}".format(BLETools.decode_mac(addr), self.__conn_handle))

			self.__ble.gap_advertise(None)
		elif event == BLEConst.IRQ.IRQ_CENTRAL_DISCONNECT:
			self.__conn_handle, _, addr, = data
			print("[{}] disconnected, handle: {}".format(BLETools.decode_mac(addr), self.__conn_handle))

			self.__conn_handle = None
			self.__advertise()
		else:
			print("event: {}, data: {}".format(event, data))

	def update_battery_level(self):
		import random
		import struct

		random.seed(random.randint(-2**16, 2**16))
		self.__ble.gatts_write(self.__handle_battery_level, struct.pack("<B", int(random.randint(1, 100))))

		if self.__conn_handle is not None:
			self.__ble.gatts_notify(self.__conn_handle, self.__handle_battery_level)


def main():
	ble_lib = BLELibTest()


if __name__ == "__main__":
	main()
